package org.dxw.common.config;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.dxw.common.ano.ReqJSON;
import org.springframework.core.MethodParameter;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;

/**
 * @description:
 * @author: dxw
 * @create: 2022-03-12 20:55
 **/
@Slf4j
public class ReqJSONResolver implements HandlerMethodArgumentResolver {

    private static final String BODY_CONTENT = "BODY_CONTENT";

    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(ReqJSON.class);
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest, WebDataBinderFactory webDataBinderFactory) throws Exception {
        HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
        JSONObject jsonObject = (JSONObject)request.getAttribute(BODY_CONTENT);
        if(jsonObject == null){
            BufferedReader reader = request.getReader();
            String json = IoUtil.read(reader);
            jsonObject = JSON.parseObject(json);
            request.setAttribute(BODY_CONTENT, jsonObject);
        }
        ReqJSON ano = methodParameter.getParameterAnnotation(ReqJSON.class);
        String name = StrUtil.isBlank(ano.name())?ano.value():ano.name();
        if(StrUtil.isBlank(name)){
            log.error("resolveArgument error ReqJSON value is empty");
            throw new RuntimeException("resolveArgument error ReqJSON value is empty");
        }
        Class<?> parameterType = methodParameter.getParameterType();
        Object paramVal = Convert.convert(parameterType, jsonObject.get(name));

        if(ObjectUtil.isEmpty(paramVal) && ano.required()){
            throw new RuntimeException("resolveArgument error "+ name +"的value is required");
        }
        return paramVal;
    }
}